package workweixin

import (
    "context"
    "crypto/tls"
    // "encoding/json"
    "net/http"
    "time"

    "github.com/beego/beego/v2/client/httplib"
    "github.com/beego/beego/v2/core/logs"
    "github.com/mindoc-org/mindoc/cache"
    "github.com/mindoc-org/mindoc/conf"
)

// doc
// - 全局错误码: https://work.weixin.qq.com/api/doc/90000/90139/90313

const (
    AccessTokenCacheKey        = "access-token-cache-key"
    ContactAccessTokenCacheKey = "contact-access-token-cache-key"
)

// 获取访问凭据-请求响应结构
type AccessTokenResponse struct {
    ErrCode     int    `json:"errcode"`
    ErrMsg      string `json:"errmsg"`
    AccessToken string `json:"access_token"` // 获取到的凭证,最长为512字节
    ExpiresIn   int    `json:"expires_in"`   // 凭证的有效时间（秒）
}

// 获取用户Id-请求响应结构
type UserIdResponse struct {
    ErrCode  int    `json:"errcode"`
    ErrMsg   string `json:"errmsg"`
    UserId   string `json:"UserId"`   // 企业成员UserID
    OpenId   string `json:"OpenId"`   // 非企业成员的标识，对当前企业唯一
    DeviceId string `json:"DeviceId"` // 设备号
}

// 获取用户信息-请求响应结构
type UserInfoResponse struct {
    ErrCode        int    `json:"errcode"`
    ErrMsg         string `json:"errmsg"`
    UserId         string `json:"UserId"`            // 企业成员UserID
    Name           string `json:"name"`              // 成员名称
    HideMobile     int    `json:"hide_mobile"`       // 是否隐藏了手机号码
    Mobile         string `json:"mobile"`            // 手机号码
    Department     []int  `json:"department"`        // 成员所属部门id列表
    Email          string `json:"email"`             // 邮箱
    IsLeaderInDept []int  `json:"is_leader_in_dept"` // 表示在所在的部门内是否为上级
    IsLeader       int    `json:"isleader"`          // 是否是部门上级(领导)
    Avatar         string `json:"avatar"`            // 头像url
    Alias          string `json:"alias"`             // 别名
    Status         int    `json:"status"`            // 激活状态: 1=已激活，2=已禁用，4=未激活，5=退出企业
    MainDepartment int    `json:"main_department"`   // 主部门
}

// 访问凭据缓存-结构
type AccessTokenCache struct {
    AccessToken string    `json:"access_token"`
    ExpiresIn   int       `json:"expires_in"`
    UpdateTime  time.Time `json:"update_time"`
}

// 企业微信用户信息-结构
type WorkWeixinUserInfo struct {
    UserId         string `json:"UserId"`            // 企业成员UserID
    Name           string `json:"name"`              // 成员名称
    HideMobile     int    `json:"hide_mobile"`       // 是否隐藏了手机号码
    Mobile         string `json:"mobile"`            // 手机号码
    Department     []int  `json:"department"`        // 成员所属部门id列表
    Email          string `json:"email"`             // 邮箱
    IsLeaderInDept []int  `json:"is_leader_in_dept"` // 表示在所在的部门内是否为上级
    IsLeader       int    `json:"isleader"`          // 是否是部门上级(领导)
    Avatar         string `json:"avatar"`            // 头像url
    Alias          string `json:"alias"`             // 别名
    Status         int    `json:"status"`            // 激活状态: 1=已激活，2=已禁用，4=未激活，5=退出企业
    MainDepartment int    `json:"main_department"`   // 主部门
}

func httpFilter(next httplib.Filter) httplib.Filter {
    return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
        r := req.GetRequest()
        logs.Info("filter-url: ", r.URL)
        // Never forget invoke this. Or the request will not be sent
        return next(ctx, req)
    }
}

// 获取访问凭据-请求
func RequestAccessToken(corpid string, secret string) (cache_token AccessTokenCache, ok bool) {
    url := "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
    req := httplib.Get(url)
    req.Param("corpid", corpid)     // 企业ID
    req.Param("corpsecret", secret) // 应用的凭证密钥
    req.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: false})
    req.AddFilters(httpFilter)
    resp, err := req.Response()
    _ = resp
    var token AccessTokenCache
    if err != nil {
        logs.Error(err)
        return token, false
    }
    var atr AccessTokenResponse
    err = req.ToJSON(&atr)
    if err != nil {
        logs.Error(err)
        return token, false
    }
    token = AccessTokenCache{
        AccessToken: atr.AccessToken,
        ExpiresIn:   atr.ExpiresIn,
        UpdateTime:  time.Now(),
    }
    return token, true
}

// 获取访问凭据
func GetAccessToken(is_contact bool) (access_token string, ok bool) {
    var cache_token AccessTokenCache
    cache_key := AccessTokenCacheKey
    if is_contact {
        cache_key = ContactAccessTokenCacheKey
    }
    err := cache.Get(cache_key, &cache_token)
    if err == nil {
        logs.Info("AccessToken从缓存读取成功")
        // TODO: access_token有效期判断, 刷新
        return cache_token.AccessToken, true
    } else {
        logs.Warning(err)
        workweixinConfig := conf.GetWorkWeixinConfig()
        logs.Debug("corp_id: ", workweixinConfig.CorpId)
        logs.Debug("agent_id: ", workweixinConfig.AgentId)
        logs.Debug("secret: ", workweixinConfig.Secret)
        logs.Debug("contact_secret: ", workweixinConfig.ContactSecret)
        secret := workweixinConfig.Secret
        if is_contact {
            secret = workweixinConfig.ContactSecret
        }
        new_token, ok := RequestAccessToken(workweixinConfig.CorpId, secret)
        if ok {
            logs.Debug(new_token)
            if err = cache.Put(cache_key, new_token, time.Second*time.Duration(new_token.ExpiresIn)); err == nil {
                logs.Info("AccessToken缓存写入成功")
                return new_token.AccessToken, true
            }
            logs.Warning("AccessToken缓存写入失败")
            return "", false
        }
        logs.Warning("AccessToken请求失败")
        return "", false
    }
}

// 获取用户id-请求
func RequestUserId(access_token string, code string) (user_id string, ok bool) {
    url := "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo"
    req := httplib.Get(url)
    req.Param("access_token", access_token) // 应用调用接口凭证
    req.Param("code", code)                 // 通过成员授权获取到的code
    req.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: false})
    req.AddFilters(httpFilter)
    resp, err := req.Response()
    _ = resp
    if err != nil {
        logs.Error(err)
        return "", false
    }
    var uir UserIdResponse
    err = req.ToJSON(&uir)
    if err != nil {
        logs.Error(err)
        return "", false
    }
    return uir.UserId, true
}

// 获取用户详细信息-请求
func RequestUserInfo(contact_access_token string, userid string) (user_info WorkWeixinUserInfo, error_msg string, ok bool) {
    url := "https://qyapi.weixin.qq.com/cgi-bin/user/get"
    req := httplib.Get(url)
    req.Param("access_token", contact_access_token) // 通讯录应用调用接口凭证
    req.Param("userid", userid)                     // 成员UserID
    req.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: false})
    req.AddFilters(httpFilter)
    resp_str, err := req.String()
    _ = resp_str
    var info WorkWeixinUserInfo
    if err != nil {
        logs.Error(err)
        return info, "请求失败", false
    } else {
        logs.Debug(resp_str)
    }
    var uir UserInfoResponse
    err = req.ToJSON(&uir)
    if err != nil {
        logs.Error(err)
        return info, "请求数据结果错误", false
    }
    if uir.ErrCode != 0 {
        return info, uir.ErrMsg, false
    }
    info = WorkWeixinUserInfo{
        UserId:         uir.UserId,
        Name:           uir.Name,
        HideMobile:     uir.HideMobile,
        Mobile:         uir.Mobile,
        Department:     uir.Department,
        Email:          uir.Email,
        IsLeaderInDept: uir.IsLeaderInDept,
        IsLeader:       uir.IsLeader,
        Avatar:         uir.Avatar,
        Alias:          uir.Alias,
        Status:         uir.Status,
        MainDepartment: uir.MainDepartment,
    }
    return info, "", true
}
